package com.tancire.question.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.tancire.common.exception.question.TrainException;
import com.tancire.common.utils.DateUtils;
import com.tancire.common.utils.SecurityUtils;
import com.tancire.common.utils.bean.BeanUtils;
import com.tancire.member.domain.MemberTrainProblem;
import com.tancire.member.service.IMemberTrainProblemService;
import com.tancire.question.domain.TrainExam;
import com.tancire.question.domain.TrainProblem;
import com.tancire.question.mapper.TrainProblemMapper;
import com.tancire.question.service.ITrainProblemService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;

/**
 * 答题题目Service业务层处理
 *
 * @author tancire
 * @date 2024-10-09
 */
@Service
public class TrainProblemServiceImpl implements ITrainProblemService {

    @Resource
    private TrainProblemMapper trainProblemMapper;

    @Resource
    private IMemberTrainProblemService memberTrainProblemService;

    /**
     * 查询答题题目
     *
     * @param id 答题题目主键
     * @return 答题题目
     */
    @Override
    public TrainProblem selectTrainProblemById(Long id) {
        return trainProblemMapper.selectTrainProblemById(id);
    }

    /**
     * 查询答题题目列表
     *
     * @param trainProblem 答题题目
     * @return 答题题目
     */
    @Override
    public List<TrainProblem> selectTrainProblemList(TrainProblem trainProblem) {
        return trainProblemMapper.selectTrainProblemList(trainProblem);
    }

    /**
     * 新增答题题目
     *
     * @param trainProblem 答题题目
     * @return 结果
     */
    @Override
    public int insertTrainProblem(TrainProblem trainProblem) {
        trainProblem.setCreateTime(DateUtils.getNowDate());
        return trainProblemMapper.insertTrainProblem(trainProblem);
    }

    /**
     * 修改答题题目
     *
     * @param trainProblem 答题题目
     * @return 结果
     */
    @Override
    public int updateTrainProblem(TrainProblem trainProblem) {
        trainProblem.setUpdateTime(DateUtils.getNowDate());
        return trainProblemMapper.updateTrainProblem(trainProblem);
    }

    /**
     * 批量删除答题题目
     *
     * @param ids 需要删除的答题题目主键
     * @return 结果
     */
    @Override
    public int deleteTrainProblemByIds(Long[] ids) {
        return trainProblemMapper.deleteTrainProblemByIds(ids);
    }

    /**
     * 删除答题题目信息
     *
     * @param id 答题题目主键
     * @return 结果
     */
    @Override
    public int deleteTrainProblemById(Long id) {
        return trainProblemMapper.deleteTrainProblemById(id);
    }

    /**
     * 获取下一个题
     *
     * @param trainProblem
     * @return
     */
    @Override
    public TrainProblem selectNextProblem(TrainProblem trainProblem) {
        Integer num = trainProblem.getNum();
        if (null == num || num < 1) {
            num = 1;
        }
        int start = num - 1;
        return trainProblemMapper.selectNextProblem(trainProblem.getTypeId(), start, 1);
    }

    /**
     * 查询题目数量
     *
     * @param trainProblem
     * @return
     */
    @Override
    public Integer selectProblemCount(TrainProblem trainProblem) {
        return this.trainProblemMapper.selectProblemCount(trainProblem);
    }

    /**
     * 随机构建题目
     *
     * @param trainExam
     * @return
     */
    @Override
    public List<TrainProblem> buildExam(TrainExam trainExam) {
        // 构建练习题
        List<Long> ids = this.trainProblemMapper.selectProblemIds(trainExam);
        Integer count = trainExam.getCount();
        if (null == count || count < 1) {
            count = 1;
        }
        List<Integer> inxList = new ArrayList<>();
        for (int i = 0; i < count; i++) {
            int index = this.randomNumber(0, ids.size() - 1);
            while (inxList.contains(index)) {
                index = this.randomNumber(0, ids.size() - 1);
            }
            inxList.add(index);
        }
        // 获取到id列表
        List<Long> queryIds = new ArrayList<>();
        for (int i = 0; i < inxList.size(); i++) {
            queryIds.add(ids.get(inxList.get(i)));
        }
        if (ObjectUtil.isEmpty(queryIds)) {
            return Collections.emptyList();
        }
        List<TrainProblem> trainProblemList = this.trainProblemMapper.selectListByIds(queryIds);
        Collections.shuffle(trainProblemList);
        return trainProblemList;
    }

    /**
     * 将题目加入错题本
     *
     * @param trainProblem
     */
    @Override
    public void addErrorProblem(TrainProblem trainProblem) {
        // 判断是否存在错题本了，存在提示不，不再重复添加
        MemberTrainProblem query = new MemberTrainProblem();
        query.setMemberId(SecurityUtils.getUserId());
        query.setProblemId(trainProblem.getId());
        List<MemberTrainProblem> memberTrainProblems = this.memberTrainProblemService.selectMemberTrainProblemList(query);
        if (ObjectUtil.isNotEmpty(memberTrainProblems)) {
            // 不处理
            return;
        }
        MemberTrainProblem memberTrainProblem = new MemberTrainProblem();
        BeanUtils.copyBeanProp(memberTrainProblem, trainProblem);
        memberTrainProblem.setProblemId(trainProblem.getId());
        memberTrainProblem.setMemberId(SecurityUtils.getUserId());
        memberTrainProblem.setId(null);
        memberTrainProblemService.insertMemberTrainProblem(memberTrainProblem);
    }

    /**
     * 查询排除活动项目的数据
     *
     * @param trainProblem
     * @return
     */
    @Override
    public List<TrainProblem> selectTrainProblemListExtr(TrainProblem trainProblem) {
        return trainProblemMapper.selectTrainProblemListExtr(trainProblem);
    }

    /**
     * 从错题本移除错题
     *
     * @param id
     */
    @Override
    public void removeErrorProblem(Long id) {
        memberTrainProblemService.deleteMemberTrainProblemById(id);
    }

    private int randomNumber(int min, int max) {
        try {
            int randomSize = max - min + 1; // 随机数的范围大小
            Random rand = SecureRandom.getInstanceStrong();
            // 生成一个特定范围内的随机数
            return min + rand.nextInt(randomSize);
        } catch (Exception e) {
            // 不处理
            throw new TrainException("随机数据产生失败！");
        }
    }
}
